<?php
/*********************************************
  Dragonfly CMS, Copyright (c) 2004 by CPGNuke Dev Team
  http://dragonflycms.org
  Released under GNU GPL version 2 or any later version
**********************************************/

abstract class Client
{

	public static
		$os,
		$name,
		$version,
		$engine,
		$engineV,
		$isMobile,
		$verified,
		$hostname,
		$languages = array();

	public static
		$ua = '',
		$browserlang = array(
		'af'    => 'afrikaans',
		'sq'    => 'albanian',
		'ar'    => 'arabic',
//		'hy'    => 'armenian',
//		'ast'   => 'asturian',
		'eu'    => 'basque',
//		'be'    => 'belarusian',
		'bs'    => 'bosanski',    // bosnian -bosanski is nuke lang name
		'bg'    => 'bulgarian',
		'ca'    => 'catalan',
		'zh'    => 'chinese_traditional', // Hong Kong, Taiwan or Malaysia
		'zh-cn' => 'chinese_simplified',  // China
//		'hr'    => 'croatian',
		'cs'    => 'czech',
		'da'    => 'danish',
		'dcc'   => 'desi',        // Deccan, India
		'nl'    => 'dutch',
		'en'    => 'english',
//		'eo'    => 'esperanto',
		'et'    => 'estonian',
//		'eu'    => 'euraska',
//		'fo'    => 'faroese',
		'fa'    => 'farsi',
		'fi'    => 'finnish',
		'fr'    => 'french',
		'gl'    => 'galego',      // galician- galego is nuke lang name
//		'ka'    => 'georgian',
		'de'    => 'german',
		'el'    => 'greek',
		'he'    => 'hebrew',
		'hi'    => 'hindi',
		'hu'    => 'hungarian',
		'is'    => 'icelandic',
		'id'    => 'indonesian',
//		'ga'    => 'irish',
		'it'    => 'italian',
		'ja'    => 'japanese',
		'ko'    => 'korean',
		'ku'    => 'kurdish',
		'lv'    => 'latvian',
		'lt'    => 'lithuanian',
		'mk'    => 'macedonian',
		'ms'    => 'malayu',
		'no'    => 'norwegian',
//		'nb'    => 'norwegian',   // bokmal
//		'nn'    => 'norwegian',   // nynorsk
		'pl'    => 'polish',
		'pt'    => 'portuguese',
		'pt-br' => 'brazilian',
		'ro'    => 'romanian',
		'ru'    => 'russian',
//		'gd'    => 'scots gealic',
		'sr'    => 'serbian',
		'sk'    => 'slovak',
		'sl'    => 'slovenian',
		'es'    => 'spanish',
		'es-es' => 'castellano',  // Spain
		'sv'    => 'swedish',
		'sw'    => 'swahili',     // Kenya and Tanzania
		'tl'    => 'tagalog',
		'th'    => 'thai',
		'tr'    => 'turkish',
		'ug'    => 'uighur',      // Turkish, Uzbek, China
		'uk'    => 'ukrainian',
		'vi'    => 'vietnamese',
//		'cy'    => 'welsh',
//		'xh'    => 'xhosa',
//		'yi'    => 'yiddish',
//		'zu'    => 'zulu',
	);

	public static function getV9Language($lng)
	{
		if (isset(self::$browserlang[$lng])) { return self::$browserlang[$lng]; }
		$lng = substr($lng,0,-3);
		if (isset(self::$browserlang[$lng])) { return self::$browserlang[$lng]; }
	}

	public static function init()
	{
		self::name();
		if (!DF_MODE_DEVELOPER && isset($_SESSION['CLIENT']['name'])) {
			if ($_SESSION['CLIENT']['name'] !== self::$name || $_SESSION['CLIENT']['version'] !== self::$version) {
				Dragonfly_Net_Http::headersFlush(400, 'User agent mismatch');
			}
			self::$name     = (string) $_SESSION['CLIENT']['name'];
			self::$version  =  (float) $_SESSION['CLIENT']['version'];
			self::$os       = (string) $_SESSION['CLIENT']['os'];
			self::$engine   = (string) $_SESSION['CLIENT']['engine'];
			self::$engineV  =  (float) $_SESSION['CLIENT']['engineV'];
			self::$isMobile =   (bool) $_SESSION['CLIENT']['isMobile'];
			self::$verified =   (bool) $_SESSION['CLIENT']['verified'];
			self::$hostname = (string) $_SESSION['CLIENT']['hostname'];
			self::$languages = (array) $_SESSION['CLIENT']['languages'];
			return;
		}
		self::os();
		self::engine();
		self::isMobile();
		self::acceptLanguages();
		if (!empty($_SESSION)) {
			$_SESSION['CLIENT']['name']     = self::$name;
			$_SESSION['CLIENT']['version']  = self::$version;
			$_SESSION['CLIENT']['os']       = self::$os;
			$_SESSION['CLIENT']['engine']   = self::$engine;
			$_SESSION['CLIENT']['engineV']  = self::$engineV;
			$_SESSION['CLIENT']['isMobile'] = self::$isMobile;
			$_SESSION['CLIENT']['verified'] = self::$verified;
			$_SESSION['CLIENT']['hostname'] = self::$hostname;
			$_SESSION['CLIENT']['languages'] = self::$languages;
		}
	}

	public static function dump()
	{
		return array(
			'name'     => self::$name,
			'os'       => self::$os,
			'version'  => self::$version,
			'engine'   => self::$engine,
			'engineV'  => self::$engineV,
			'isMobile' => self::$isMobile,
			'verified' => self::$verified,
			'hostname' => self::$hostname,
			'languages' => self::$languages
		);
	}

	public static function dumpToText()
	{
		$ret = array();
		foreach (self::dump() as $k => $v) {
			if (is_array($v)) $v = implode(',', array_keys($v));
			$ret[] = "$k: $v";
		}
		trigger_error(implode("<br/>\n", $ret), E_USER_WARNING);
		return implode("<br/>\n", $ret);
	}

	/** Return null values on failure */
	protected static function name()
	{
		if (empty($_SERVER['HTTP_USER_AGENT'])) return;
		self::$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
		/*
		 * swiftfox, epiphany, flock and galeon have "firefox" in their UA
		 * chimera is an on old name of camino
		 * midori, omniweb, shiira and sunrise have "safari" in their UA
		 * We don't detect MyIE2, AOL and America Online branded versions of MSIE
		 * Sylera is a Japanese Gecko based browser
		 */
		if(preg_match('#(ie)[/\s](1?[0-9](\.[0-9])?)#', self::$ua, $match)
		|| preg_match('#(epiphany|flock|galeon|midori|omniweb|swiftfox)#', self::$ua, $match)
		|| preg_match('#(chrome|safari|firefox|netsurf)/([0-9]+(\.[0-9]+)?)#', self::$ua, $match)
		|| preg_match('#(crazy|maxthon|avant|webtv|ubvision|slimbrowser|swiftweasel)#', self::$ua, $match)
		|| preg_match('#(elinks|opera|shiira|devontech|ibrowse|icab|conkeror|chimera|classilla|gnuzilla|iceweasel|iceape)#', self::$ua, $match)
		|| preg_match('#(konqueror|voyager|links|lynx|w3m|dillo|netscape|thunderbird|camino|seamonkey|linspire|multizilla|k\-meleon|kazehakase|minimo)#', self::$ua, $match)
		|| preg_match('#(webwasher)#', self::$ua, $match))
		{
			self::$name = $match[1];
			if (isset($match[2])) { self::$version = intval($match[2]); }
			if (('opera' === self::$name || 'safari' === self::$name) && preg_match('#version/([0-9]+(\.[0-9]+)?)#', self::$ua, $match)) {
				self::$version = floatval($match[1]);
			}
			else if ('ie' === self::$name) { self::$name = 'msie'; }
		}
		/*
		 * firebird and phoenix are old names for firefox
		 * bonecho, granparadiso, minefield are develop names for firefox
		 */
		else if (preg_match('#(firebird|phoenix|bonecho|granparadiso|minefield|shiretoko)[\/ ]([0-9]+(\.[0-9]+)?)#', self::$ua)) {
			self::$name = 'firefox';
		}
		else if (preg_match('#^mozilla/5.+gecko/200#', self::$ua)) {
			self::$name = 'mozilla';
		}
	}

	/** Returns null values on failure */
	protected static function os()
	{
		if (preg_match('#(windows|mac|android|linux|bsd|sunos|syllable|irix|beos|os/2|aix|amiga|react|javafx|palm|nintendo|playstation|darwin)#', self::$ua, $match)
		 || preg_match('#(symbian|blackberry|iphone|meego|maemo|ipad|x11)#', self::$ua, $match))
		{
			switch ($match[1]):
				case 'win':
					self::$os = 'windows';
					break;
				case 'iphone':
				case 'ipad':
					self::$os = 'ios';
					break;
				case 'maemo':
				case 'meego':
					self::$os = 'linux';
					break;
				default:
					self::$os = $match[1];
					break;
			endswitch;
		}
	}

	/** Return null values on failure */
	protected static function engine()
	{
		if (preg_match('#(apachebench|dillo|gecko|khtml|presto|trident|up\.browser|webkit|libwww|java|netsurf)[\/ ]([0-9]+(\.[0-9]+)?)#', self::$ua, $match)
		|| preg_match('#(msie|opera)[\/ ]([0-9]+(\.[0-9]+)?)#', self::$ua, $match)) {
			/*
			 * IE9 and IE8 includes Trident version in their UA so we only look for empty ones
			 * IE8 in compatibility mode identify itClient as IE7 but leaves trident/4.0 in the UA
			 */
			if ('msie' === $match[1] || ('trident' === $match[1] && false !== strpos(self::$ua, 'msie 7'))) {
				self::$engine = 'trident';
				self::$engineV = 3.0;
			} else {
				if ('opera' == $match[1]) { $match[1] = 'presto'; }
				self::$engine = $match[1];
				self::$engineV = floatval($match[2]);
			}
		}
	}

	/** Return int */
	protected static function isMobile()
	{
		self::$isMobile = (int) !empty($_SERVER['HTTP_X_OPERAMINI_PHONE'])
		|| isset($_SERVER['HTTP_ACCEPT']) && false !== strpos(strtolower($_SERVER['HTTP_ACCEPT']), '/vnd.wap.') // xhtml+xml | wml
		|| self::$os == 'android'
		|| self::$os == 'symbian'
		|| self::$os == 'blackberry'
		|| self::$os == 'ios'
		|| false !== strpos(self::$ua, 'windows ce')
		|| false !== strpos(self::$ua, 'mobile')
		|| false !== strpos(self::$ua, 'epoc')
		|| false !== strpos(self::$ua, 'opera mini')
		|| false !== strpos(self::$ua, 'opera mobi')
		|| false !== strpos(self::$ua, 'maemo')
		|| false !== strpos(self::$ua, 'minimo')
		|| false !== strpos(self::$ua, 'nitro')
		|| false !== strpos(self::$ua, 'j2me')
		|| false !== strpos(self::$ua, 'midp-')
		|| false !== strpos(self::$ua, 'cldc-')
		|| false !== strpos(self::$ua, 'netfront')
		|| false !== strpos(self::$ua, 'mot')
		|| false !== strpos(self::$ua, 'up.browser')
		|| false !== strpos(self::$ua, 'up.link')
		|| false !== strpos(self::$ua, 'sony')
		|| false !== strpos(self::$ua, 'nokia')
		|| false !== strpos(self::$ua, 'samsung')
		|| false !== strpos(self::$ua, 'audiovox')
		|| false !== strpos(self::$ua, 'ericsson')
		|| false !== strpos(self::$ua, 'panasonic')
		|| false !== strpos(self::$ua, 'philips')
		|| false !== strpos(self::$ua, 'sanyo')
		|| false !== strpos(self::$ua, 'sharp')
		|| false !== strpos(self::$ua, 'sie-')
		|| false !== strpos(self::$ua, 'portalmmm')
		|| false !== strpos(self::$ua, 'blazer')
		|| false !== strpos(self::$ua, 'avantgo')
		|| false !== strpos(self::$ua, 'danger')
		|| false !== strpos(self::$ua, 'palm')
		|| false !== strpos(self::$ua, 'series60')
		|| false !== strpos(self::$ua, 'palmsource')
		|| false !== strpos(self::$ua, 'pocketpc')
		|| false !== strpos(self::$ua, 'smartphone')
		|| false !== strpos(self::$ua, 'rover')
		|| false !== strpos(self::$ua, 'ipaq')
		|| false !== strpos(self::$ua, 'au-mic')
		|| false !== strpos(self::$ua, 'alcatel')
		|| false !== strpos(self::$ua, 'ericy')
		|| false !== strpos(self::$ua, 'vodafone/')
		|| false !== strpos(self::$ua, 'wap1.')
		|| false !== strpos(self::$ua, 'wap2.')
		|| false !== strpos(self::$ua, 'portable');
	}

	/*
	options
	basedir: "install" for install languages, "main" for main language including l10n modules dir
	default: the fallback language
	get: $_GET to look for
	cookie: $_COOKIE to look for
	set: set the cookie
	*/
	protected static function acceptLanguages(array $options=array())
	{
		if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
			self::$languages['en'] = 'en';
			return;
		}

		# split and sort accepted languages by rank (q)
		if (preg_match_all('#(?:^|,)([a-z\-]+)(?:;\s*q=([0-9.]+))?#', mb_strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']), $languages, PREG_SET_ORDER))
		{
			foreach ($languages as $lang) {
				if (!isset($lang[2])) { $lang[2] = 1; }
				if (2 > $lang[2]) {
					self::$languages[sprintf('%f%d', $lang[2], rand(0,9999))] = $lang[1];
				}
				else { self::$languages[$lang[2]] = $lang[1]; }
			}
			krsort(self::$languages);
		}
	}

}

Client::init();
